#include <stdlib.h>
#include "include/analysesyntaxiquebis.h"
#include "include/gestiondetypes.h"
#include "include/gestiondesmessages.h"
#include <string.h>
#include "include/analysesyntaxique.h"
#include <math.h>
#include <limits.h>

LIGNE_INSTRUCT_ASM * main_analysesyntaxiquebis(LIGNE_INSTRUCT_ASM *index_instruct, LISTE Letiquette, INSTRUCTION *dico_instruct )
{
    int ligne_i,j,n;
    LIGNE_INSTRUCT_ASM * t_instruct = index_instruct;
    /// I Remplacer pseudoinstruct & {LU, SW}+etq

    for(ligne_i=0; t_instruct[ligne_i].num_instruction !=-1 ; ligne_i++)
    {
        //contient_symb(index_instruct[ligne_i]);
        //visualiser_tableau_ligne_text(t_instruct,dico_instruct);

        if((dico_instruct[t_instruct[ligne_i].num_instruction].type==7 && dico_instruct[t_instruct[ligne_i].num_instruction].nb_param)>1 ||	\
                    (dico_instruct[t_instruct[ligne_i].num_instruction].type==8 && contient_symb(t_instruct[ligne_i]) )   	)
        {
            //Si on doit modifier la liste d'etq
            ecriremessage(NIVEAU_DEBUG,"Test modif liste etq\n");
            //modif la liste d'etq
            n=1;
            if (dico_instruct[t_instruct[ligne_i].num_instruction].type==7)
            {
                // On s'assure de savoir combien de ligne seront a rajoute en cas de pseudo-instruct
                n=dico_instruct[t_instruct[ligne_i].num_instruction].nb_param - 1;
            }
            ecriremessage(NIVEAU_DEBUG, "On va rajouter %d ligne(s) dans les etiquettes et le .text.\n", n);

            for (j=0; j<n; j++)
            {
                ecriremessage(NIVEAU_DEBUG,"\n");
                ecriremessage(NIVEAU_DEBUG,"Premiere visualisation du tableau text\n");
                visualiser_tableau_ligne_text(t_instruct, dico_instruct);
                incrementer_liste_etiquette(Letiquette, ligne_i);

                ecriremessage(NIVEAU_DEBUG,"\n");
                ecriremessage(NIVEAU_DEBUG,"Deuxieme visualisation du tableau text\n");

                visualiser_tableau_ligne_text(t_instruct, dico_instruct);
                t_instruct = ajout_tab_ligne_instruct(t_instruct,ligne_i, dico_instruct);
                //            visualiser_tableau_ligne_text(t_instruct, dico_instruct);
                remplacer_ligne_instruct(t_instruct,ligne_i,dico_instruct);
                //          visualiser_tableau_ligne_text(t_instruct, dico_instruct);

            }
            ligne_i = ligne_i+n;

        }
    }
    ecriremessage(NIVEAU_DEBUG,"FIN de partie I dans mainanalysesyntaxiquebis\n");
    visualiser_tableau_ligne_text(t_instruct,dico_instruct);

    // II Remplacer les etiquettes & verif des instructions

    for(ligne_i=0; t_instruct[ligne_i].num_instruction !=-1 ; ligne_i++)
    {
        if (contient_symb(t_instruct[ligne_i]) )
        {
//			ecriremessage(NIVEAU_DEBUG,"Test 5 \n\n\n\n\n");
            remplacer_etq(t_instruct,ligne_i,Letiquette, dico_instruct);
        }

//		ecriremessage(NIVEAU_DEBUG,"Test 6 \n\n\n\n\n");

        verif_type_argument_instruct(&t_instruct[ligne_i],dico_instruct);
		ecriremessage(NIVEAU_INFO,"Adresse ASM : 0x%04X \t\tCode ASM : 0x%.8X \n",ligne_i*4,t_instruct[ligne_i].code_final);
    }

	ecriremessage(NIVEAU_DEBUG,"-------- FIN ANALYSESYNTAXIQUEBIS ---------\n");
	ecriremessage(NIVEAU_DEBUG,"\n");
	ecriremessage(NIVEAU_DEBUG,"\n");

	for(ligne_i=0; t_instruct[ligne_i].num_instruction !=-1 ; ligne_i++)
		ecriremessage(NIVEAU_INFO,"Adresse ASM : 0x%04X \t\tCode ASM : 0x%.8X \n",ligne_i*4,t_instruct[ligne_i].code_final);

	visualiser_tableau_ligne_text(t_instruct,dico_instruct);

	return t_instruct;

}



int contient_symb(LIGNE_INSTRUCT_ASM ligne)
{
    int i=0;
    LISTE index;
    for (i=0; ligne.tab_liste[i] && i<NOMBRE_MAX_D_OPERANDES ; i++)
    {
        index = ligne.tab_liste[i];

        if ( ((ELEMENT_LEXEME*)(index->element))->type_de_lexeme == TYPE_Symbole)
        {
    /**/    if ( !est_vide(index->suivant) )
    /**/    {
    /**/        ecriremessage(NIVEAU_ERROR,"Erreur dans le code ASM a la ligne %03d : <%s>\n",\
    /**/    /**/              ((ELEMENT_LEXEME*)(index->element))->num_ligne_lexeme,\
    /**/    /**/              ((ELEMENT_LEXEME*)(index->element))->chaine_lexeme);
    /**/        exit(EXIT_FAILURE);
    /**/    }
    /**/    return i+1;
        }
    }
    return 0;
}

ELEMENT_ETIQUETTE* identif_etiquette(ELEMENT_LEXEME lexeme, LISTE Letiquette)
{
    LISTE index = Letiquette;
    while (!est_vide(index))
    {
        if (!strcmp(  ( (ELEMENT_ETIQUETTE*)(index->element) )->nom, lexeme.chaine_lexeme))
    /**/    return index->element;
        index=index->suivant;
    }
    ecriremessage(NIVEAU_WARNING,"Ligne %03d : <%s>, l'etiquette n'est pas definie dans le code ASM \n",\
                  lexeme.num_ligne_lexeme,lexeme.chaine_lexeme);

    ELEMENT_ETIQUETTE *pelementdelaliste = calloc(1, sizeof(ELEMENT_ETIQUETTE));
    if(!pelementdelaliste)
    {
        ecriremessage(NIVEAU_ERROR,"Allocation dynamique echouee dans analysesyntaxiquebis: identif_etiquette.");
        exit(EXIT_FAILURE);
    }
    pelementdelaliste->nom=strdup(lexeme.chaine_lexeme);
    pelementdelaliste->num_ligne = 0;
    pelementdelaliste->type=0;

    ajout_queue((void*)pelementdelaliste,Letiquette);
    return pelementdelaliste;
}


void remplacer_etq(LIGNE_INSTRUCT_ASM *t_instruct, int ligne,LISTE Letiquette, INSTRUCTION *dico_instruct)
{
    LIGNE_INSTRUCT_ASM instruct=t_instruct[ligne];
    char chaine[30];
    ELEMENT_ETIQUETTE etq;
    int index,n,j;

	//	ecriremessage(NIVEAU_DEBUG,"Test 5+++ \n\n\n\n\n");

    if (instruct.num_instruction ==-2)
    {// On est dans le cas LUI + LW/SW avec les etqs

        t_instruct[ligne].num_instruction = identif_instruction(dico_instruct,"LUI",0);
		// On remplit le champ num_instruction de LUI

        sprintf(chaine,"$1");
        t_instruct[ligne].tab_liste[0] = ajout_queue_liste_lexeme(NULL, TYPE_Registre,chaine,0);
		// On remplit le champ de operande 0 de LUI par $1

		etq = *identif_etiquette( (*(ELEMENT_LEXEME*)(t_instruct[ligne].tab_liste[1]->element)),Letiquette);
		// On reconnait l'etq

		sprintf(chaine,"%x",etq.num_ligne * 4 / 65536);// 65536 = 2^16
        if (  (etq.num_ligne*4) % 65536 >= 32768 )
        {
			//	ecriremessage(NIVEAU_DEBUG,"Test 5+++013 \n\n\n\n\n");
            //32768 = 2^15  => Si les 16 bits de poids faibles sont supperieurs a 2^15 (bit de signe | de poid fort)
            sprintf(chaine,"0x%x",(etq.num_ligne * 4 / 65536)+1);
        }
        t_instruct[ligne].tab_liste[1] = ajout_queue_liste_lexeme(NULL, TYPE_Valeur_hexadecimale,chaine,0);
		// On met les 16 bits de poids fort de l'etq dans LUI


		/// LUI FINI /////////////////////////////////////////

        t_instruct[ligne+1].tab_liste[0] = ajout_queue_liste_lexeme(NULL, 	((ELEMENT_LEXEME*)(instruct.tab_liste[0]->element))->type_de_lexeme,\
										((ELEMENT_LEXEME*)(instruct.tab_liste[0]->element))->chaine_lexeme,0);
		// On met la premiere operande de "LW/SW $rt, etq" dans l'opperande de LW;
        sprintf(chaine,"0x%x",(etq.num_ligne * 4) % 65536);
        t_instruct[ligne+1].tab_liste[1]=ajout_queue_liste_lexeme(NULL, TYPE_Valeur_hexadecimale,chaine,0);
		//On met les 16 bits de poids faible dans l'opperande 2 de LW/SW

        sprintf(chaine, "(");
        t_instruct[ligne+1].tab_liste[1]=ajout_queue_liste_lexeme(t_instruct[ligne+1].tab_liste[1], TYPE_Parenthese_gauche,chaine,0);

        sprintf(chaine,"$%d",1);
        t_instruct[ligne+1].tab_liste[1]=ajout_queue_liste_lexeme(t_instruct[ligne+1].tab_liste[1], TYPE_Registre,chaine,0);

        sprintf(chaine, ")");
        t_instruct[ligne+1].tab_liste[1]=ajout_queue_liste_lexeme(t_instruct[ligne+1].tab_liste[1], TYPE_Parenthese_droite,chaine,0);

		for(j=0 ; j<NOMBRE_MAX_D_OPERANDES ; j++)
		{
			liberer_liste_lexemes(instruct.tab_liste[j]);
		}

        return;

    }
    //ecriremessage(NIVEAU_DEBUG,"Test 9+ \n%d  - %s \n\n\n\n",((ELEMENT_LEXEME*)(instruct.tab_liste[0]->element))->type_de_lexeme,((ELEMENT_LEXEME*)(instruct.tab_liste[0]->element))->chaine_lexeme);


    if (instruct.num_instruction==8)
    {
        return;
    }


    index= contient_symb(instruct);
	while (index)
	{
		// tant qu'il y a une etiquette
		etq = * identif_etiquette( *( (ELEMENT_LEXEME*)(t_instruct[ligne].tab_liste[index-1]->element) ), Letiquette );



        // IL reste a liberer l' element etiquette

        free((ELEMENT_LEXEME*)(t_instruct[ligne].tab_liste[index-1]->element));

        ecriremessage(NIVEAU_DEBUG, "%deme instruction, Num d'instruction : %d et index-1 : %d.\n", ligne, instruct.num_instruction, index-1);
        switch (dico_instruct[instruct.num_instruction].type_operande[index-1])
        {
				//&t_instruct[17]
			case 'I'://un immediat est sur 16 bits signes
				n = (etq.num_ligne*4) % 0x10000;// 65.536 = 2^16 = 16^4 = 0x10000
				if (n>0x7FFF)//32.767 = 2^15-1 = 2^(3*4+3) - 1 = 16^3 * 8 - 1 = 0x8000-1 = 0x7FFF
				{
					n = n - 0x10000;
				}// La valeur de l'etiquette est calcule pour ses 16 bits signes de poids faible

				sprintf(chaine,"%d", n);
				t_instruct[ligne].tab_liste[index-1]=ajout_queue_liste_lexeme(NULL, TYPE_Valeur_decimale,chaine,0);//On met la valeur calcule a la place de l'etq

				break;

			case 'O':

				n = ((etq.num_ligne - (ligne +1))*4) % 0x40000;// 262.144 = 2^18 = 2^(4*4 + 2) = 0x4 * 0x10000 = 0x40000
				if (n>0x1FFFF)//131.071 = 2^17-1
				{
					n = n - 0x40000;
				}

				sprintf(chaine,"%d", n);
				t_instruct[ligne].tab_liste[index-1]=ajout_queue_liste_lexeme(NULL, TYPE_Valeur_decimale,chaine,0);   // ça a bavé parce que Xtian a oublié le "-1". C'est pas bien! Vive le débuggeur !
				// la valeur que renvoie ajout_queue_liste_lexeme bave sur le t_instruct suivant

				break;

			case 'T':
				ecriremessage(NIVEAU_DEBUG,"Valeur etq target : %d \t0x%x\n",etq.num_ligne,etq.num_ligne);
				n = (etq.num_ligne*4) % 0x10000000;// 268.435.456 = 2^28
				if (n>0x7FFFFFF)//134.217.727 = 2^27-1
				{
					n = n - 0x10000000;
				}

				sprintf(chaine,"%d", n);
				t_instruct[ligne].tab_liste[index-1]=ajout_queue_liste_lexeme(NULL, TYPE_Valeur_decimale,chaine,0);

				break;

			default:
				ecriremessage(NIVEAU_ERROR,"Erreur dans le code ASM a la ligne %03d : <%s>.\n" ,\
							  ((ELEMENT_LEXEME*)(instruct.tab_liste[index-1]->element))->num_ligne_lexeme,\
							  ((ELEMENT_LEXEME*)(instruct.tab_liste[index-1]->element))->chaine_lexeme);
				exit(EXIT_FAILURE);
				break;
        }
        instruct=t_instruct[ligne];
		index = contient_symb(instruct);
	}

}



void incrementer_liste_etiquette(LISTE Letiquette,int ligne_i)
{
    LISTE index = Letiquette;

    while (!est_vide(index))
    {
        if (  ( (ELEMENT_ETIQUETTE*)(index->element) )->num_ligne  > (unsigned int) ligne_i &&\
                ( (ELEMENT_ETIQUETTE*)(index->element) )->type >0  )
        {
            ( (ELEMENT_ETIQUETTE*)(index->element) ) -> num_ligne++;
        }
        index = index->suivant;
    }
}


LIGNE_INSTRUCT_ASM* ajout_tab_ligne_instruct( LIGNE_INSTRUCT_ASM* t_instruct, int offset, INSTRUCTION dictionnaire_instruction[] )
{
/*
    if (tab_ligne_instruct_leng(t_instruct, dictionnaire_instruction) > 40)
    {
        ecriremessage(NIVEAU_ERROR,"Le -1 a ete supprime : taille = %d",tab_ligne_instruct_leng(t_instruct, dictionnaire_instruction));
        exit(EXIT_FAILURE);
    }
*/
    t_instruct = realloc(t_instruct, sizeof(LIGNE_INSTRUCT_ASM) * (tab_ligne_instruct_leng(t_instruct, dictionnaire_instruction) + 2 ) );

    ecriremessage(NIVEAU_DEBUG, "\n");

    visualiser_tableau_ligne_text(t_instruct, dictionnaire_instruction);
    ecriremessage(NIVEAU_DEBUG, "On decale la ligne_instruct vers la droite a partir de l\'offset %d\n", offset);
    decaler_ligne_instruct_vers_droite(t_instruct, offset, dictionnaire_instruction);

    ecriremessage(NIVEAU_DEBUG, "\n");

    visualiser_tableau_ligne_text(t_instruct, dictionnaire_instruction);
/*
    if (tab_ligne_instruct_leng(t_instruct, dictionnaire_instruction)>40)
    {
        ecriremessage(NIVEAU_ERROR,"Le -1 a ete supprime! Taille = %d :-(\n",tab_ligne_instruct_leng(t_instruct, dictionnaire_instruction));
        exit(EXIT_FAILURE);
    }
*/
    return t_instruct;
}

void decaler_ligne_instruct_vers_droite(LIGNE_INSTRUCT_ASM* tab,int offset, INSTRUCTION dictionnaire_instruction[])
{
    LIGNE_INSTRUCT_ASM* pointeur=tab;
    /*
    if ( (tab[offset].num_instruction) !=-1)
    {
        decaler_ligne_instruct_vers_droite(tab,offset+1);
    }
    tab[offset+1]=tab[offset];
    */
    ecriremessage(NIVEAU_DEBUG, "Pointeur de tab avant le decalage : %p\n", tab);

    pointeur = memmove( tab+offset+1 , tab+offset , ( tab_ligne_instruct_leng(tab, dictionnaire_instruction) - offset +1 )*sizeof(LIGNE_INSTRUCT_ASM) ); // Look mom, no hands!!

    /*
    Note sur memmove :
    On n'a pas besoin de sizeof()*offset dans *dest et *src, mais par contre on en a besoin dans n ! C'est bizarre !
    */

    ecriremessage(NIVEAU_DEBUG, "Pointeur de memmove dans le decalage : %p.\n", pointeur);
    ecriremessage(NIVEAU_DEBUG, "sizeof(LIGNE_INSTRUCT_ASM)=%d.\n", sizeof(LIGNE_INSTRUCT_ASM));
    ecriremessage(NIVEAU_DEBUG, "Pointeur de tab apres le decalage : %p.\n", tab);
    tab_ligne_instruct_leng(tab, dictionnaire_instruction);	// on n'utilise pas la valeur renvoyee
}

int tab_ligne_instruct_leng(LIGNE_INSTRUCT_ASM* t_instruct, INSTRUCTION * dico)
{
    int i=0;
    while ( (t_instruct[i].num_instruction!=-1)  && (i<99)  )	// ça bug ! :(
    {
        ecriremessage(NIVEAU_DEBUG, "Le tableau a au moins %3d instructions et t_instruct[%3d].num_instruction==%3d i.e. <<%5s>>.\n", i+1,i, t_instruct[i].num_instruction, dico[
t_instruct[i].num_instruction ].nom);
        i++;
    }

    ecriremessage(NIVEAU_DEBUG,"Le tableau a %d instructions.\n", i);
    return i;
}

void remplacer_ligne_instruct(LIGNE_INSTRUCT_ASM* tab,int ligne,INSTRUCTION *dico_instruct)
{
    int i,j;
    char chaine[30];

    LIGNE_INSTRUCT_ASM originale = tab[ligne];// On enregistre l'originale
    /*for (i=0; !est_vide(tab[ligne].tab_liste[i]); i++)
    {// Puis on le desalloue
    	liberer_liste_lexemes();
    }*/

    if (dico_instruct[ originale.num_instruction ].type == 7 )
    {
        // Si c'est une pseudo-instruction
        for (i=0; i < dico_instruct[ originale.num_instruction ].nb_param; i++)
        {
            //pour chaque "valeur ligne" a remplacer
            tab[ligne + i].num_instruction = dico_instruct[originale.num_instruction]\
                                             .chaine_instruction[i];//On remplace le numero de l'instruction

            for (j=0; j < dico_instruct[ tab[ligne + i].num_instruction ].nb_op / 10 ; j++)
            {
                // Pour chaque operande a remplacer
                if (dico_instruct[ originale.num_instruction ].valeur_operande[i][j] % 10 == 0)
                {
                    // Si la valeur de la j-eme opperande de la i-eme ligne est une valeur "dure" (definie au depart)
                    switch (dico_instruct[ tab[ligne + i].num_instruction ].type_operande[j])
                    {
                    case '$':
                        sprintf(chaine,"$%d", dico_instruct[ originale.num_instruction ].valeur_operande[i][j]/10);
                        tab[ligne + i].tab_liste[j] = ajout_queue_liste_lexeme(NULL, TYPE_Registre,chaine,0);
                        break;

                    case 'I':
                    case 'O':
                    case 'T':
                    case 'S':
                        sprintf(chaine,"%d", dico_instruct[ originale.num_instruction ].valeur_operande[i][j]/10);
                        tab[ligne + i].tab_liste[j] = ajout_queue_liste_lexeme(NULL, TYPE_Valeur_decimale,chaine,0);
                        break;

                    case 'N':
                        ecriremessage(NIVEAU_ERROR,"ERREUR COMPILATEUR : L'ADRESSAGE INDIRECT N'A PAS\
										  ETE IMPLEMENTE POUR LES PSEUDO-INSTRUCTIONS");
                        exit(EXIT_FAILURE);
                        break;

                    default:
                        ecriremessage(NIVEAU_ERROR,"ERREUR DANS LE DICTIONAIRE D'INSTRUCTION :\
										  LE TYPE DE PSEUDO-INSTRUCTION <%c> NE RENVOIE A RIEN",\
                                      dico_instruct[ tab[ligne + i].num_instruction ].type_operande[j]);
                        exit(EXIT_FAILURE);
                        break;
                    }
                }
                else
                {
                    //Si la valeur de la j-eme opperande de la i-eme ligne est definie par rapport a

                    tab[ligne +i ].tab_liste[j] = \
                                                  originale.tab_liste[   dico_instruct[ originale.num_instruction ]\
                                                          .valeur_operande[i][j]   ];
                    /*Bon, la c'est un peu subtil (^u^)
                     en gros :
                    	- originale.num_instruction nous donne le numero de la pseudo-instruction
                    	- on regarde dans le dico la valeur que la j-eme opperande de la i-eme ligne
                    	- dans le cas present (le else) il s'agit de l'opperande de la pseudo-
                     instruction originale, on en prend donc son opperande a l'indice que l'on
                     vient d'obtenir
                    	- puis, il nous reste a affecter cette operande (de type liste) a la
                     bonne instruction du tableau, et surtout a la bonne operande*/

                }
            }
        }
        return;
    }

    if (dico_instruct[ originale.num_instruction ].type == 8 )
    {
        // S'il s'agit de LW / SW comprenant une etiquette
        tab[ligne].num_instruction = -2;
        tab[ligne+1].num_instruction = originale.num_instruction;
        return;
    }
    ecriremessage(NIVEAU_ERROR,"BUG COMPILATEUR ASM DANS LA FONCTION REMPLACER_LIGNE_INSTRUCT");
    exit(EXIT_FAILURE);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void verif_type_argument_instruct(LIGNE_INSTRUCT_ASM *pligne, INSTRUCTION *dico_instruct)
{
    int i=0;
	int n=0;
	int reg_adressage_indirect;
	LIGNE_INSTRUCT_ASM ligne =*pligne;

	ligne.code_final = dico_instruct[ligne.num_instruction].cache;

    for (i=0; i<dico_instruct[ligne.num_instruction].nb_op/10; i++)
    {
		ecriremessage(NIVEAU_DEBUG,"verif_type_argument = Lexeme etudie en cours : %s de type %s \n",\
					 ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->chaine_lexeme,\
					 traduire_type_lexeme(((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->type_de_lexeme));

        switch (dico_instruct[ligne.num_instruction].type_operande[i])
        {
			case '$':
///				ecriremessage(NIVEAU_DEBUG,"DEBUG,BLOP\n");
				ligne.code_final = ligne.code_final + num_registre(  *( (ELEMENT_LEXEME*)(ligne.tab_liste[i]->element) )  ) * \
				( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i]  ));

				//ecriremessage(NIVEAU_DEBUG,"DEBUG,BLiP 0x%X\n",ligne.code_final,dico_instruct[ligne.num_instruction].taille_parametre[i] );

				if (!est_vide(ligne.tab_liste[i]->suivant))
				{
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%s> doit etre un registre \n",\
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->suivant->element))->num_ligne_lexeme ),\
								    ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->suivant->element))->chaine_lexeme);
					exit(EXIT_FAILURE);
				}

				break;

/*
 case 'I'://un immediat est sur 16 bits signes
 n = (etq.num_ligne*4) % 0x10000;// 65.536 = 2^16 = 16^4 = 0x10000
 if (n>0x7FFF)//32.767 = 2^15-1 = 2^(3*4+3) - 1 = 16^3 * 8 - 1 = 0x8000-1 = 0x7FFF
 {
 n = n - 0x10000;
 }// La valeur de l'etiquette est calcule pour ses 16 bits signes de poids faible

 case 'O':

 n = (etq.num_ligne*4) % 0x40000;// 262.144 = 2^18 = 2^(4*4 + 2) = 0x4 * 0x10000 = 0x40000
 if (n>0x1FFFF)//131.071 = 2^17-1
 {
 n = n - 0x40000;
 }

 sprintf(chaine,"%d", n);
 t_instruct[ligne].tab_liste[index-1]=ajout_queue_liste_lexeme(NULL, TYPE_Valeur_decimale,chaine,0);
 // la valeur que renvoie ajout_queue_liste_lexeme bave sur le t_instruct suivant


 break;

 case 'T':

 n = (etq.num_ligne*4) % 0x10000000;// 268.435.456 = 2^28
 if (n>0x7FFFFFF)//134.217.727 = 2^27-1
 {
 n = n - 0x10000000;
 }
*/
			case 'I':
				n = lire_nombre(ligne.tab_liste[i]);

				if (n>=0xFFFF || n <= -0xFFFF)
				{
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%s> =0x%X est un nombre de taille incorrect : c'est une valeur immediate. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ),\
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->chaine_lexeme ),\
								  n);
				}

				ligne.code_final = ligne.code_final +  ( (unsigned int)(n) )* \
				( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i]  ));

				break;

			case 'N':

				n = lire_adressage_indirect(ligne.tab_liste[i], &reg_adressage_indirect);

				ligne.code_final = ligne.code_final +  reg_adressage_indirect * \
				( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i+1]  )) + ( (unsigned int)(n)  )\
				*( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i]  ));

				break;

			case 'O':

				n = lire_nombre(ligne.tab_liste[i]);

				if (n%4 !=0) {
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%d> doit etre un multiple de 4. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ),\
								  n);
				}
				n=n/4;

				if (n >= 0xFFFF || n <= -0xFFFF)
				{
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%s> = 0x%X est un nombre de taille incorrect : c'est une valeur comprise entre -0xFFFF et 0xFFFF. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ) ,\
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->chaine_lexeme ),\
								  n);
				}

				ligne.code_final = ligne.code_final +  ( (unsigned int)(n) )* \
				( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i]  ))/4;

				break;

			case 'T':
				n = lire_nombre(ligne.tab_liste[i]);

				if (n%4 !=0) {
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%d> doit etre un multiple de 4. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ),\
								  n);

				}
				ecriremessage(NIVEAU_DEBUG,"Nombre lu dans le champs target : %d\n",n);
				n=n/4;

				if ((n>>28) > 0 || n < 0)
				{
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%s> = 0x%X est un nombre de taille incorrect : c'est une valeur comprise entre -0xFFFF et 0xFFFF. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ) ,\
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->chaine_lexeme ),\
								  n);
				}

				ligne.code_final = ligne.code_final + ( lire_nombre(ligne.tab_liste[i]) * n \
														<< ( dico_instruct[ligne.num_instruction].position_parametre[i] ))    ;
				break;

			case 'S':
				n = lire_nombre(ligne.tab_liste[i]);

				if (n > 0x1F || n < 0)
				{
					ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%d> est un nombre de taille incorrect : c'est une valeur comprise entre 0 et 0x1F. \n",
								  ( ((ELEMENT_LEXEME*)(ligne.tab_liste[i]->element))->num_ligne_lexeme ),\
								  n);
				}

				ligne.code_final = ligne.code_final +  ( (unsigned int)(n) )* \
				( (unsigned int)pow(2,dico_instruct[ligne.num_instruction].position_parametre[i]  ));
				break;

			default:
				exit(EXIT_FAILURE);
				break;
        }
    }
	*pligne=ligne;
}


unsigned int num_registre(ELEMENT_LEXEME lexeme)

{
	ecriremessage(NIVEAU_DEBUG, "num_registre => lexeme : %s, type de registre : %s\n", lexeme.chaine_lexeme, traduire_type_lexeme( lexeme.type_de_lexeme));

	if (lexeme.type_de_lexeme!=TYPE_Registre)
	{
		ecriremessage(NIVEAU_ERROR,"Ligne %03d : <%s> doit etre un registre \n",\
					  lexeme.num_ligne_lexeme,lexeme.chaine_lexeme);
		exit(EXIT_FAILURE);
	}

	if (!strcmp(lexeme.chaine_lexeme,"$zero")||\
		!strcmp(lexeme.chaine_lexeme,"$0"))
	{
		return 0;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$at")||\
		!strcmp(lexeme.chaine_lexeme,"$1"))
	{
		return 1;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$v0")||\
		!strcmp(lexeme.chaine_lexeme,"$2"))
	{
		return 2;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$v1")||\
		!strcmp(lexeme.chaine_lexeme,"$3"))
	{
		return 3;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$a0")||\
		!strcmp(lexeme.chaine_lexeme,"$4"))
	{
		return 4;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$a1")||\
		!strcmp(lexeme.chaine_lexeme,"$5"))
	{
		return 5;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$a2")||\
		!strcmp(lexeme.chaine_lexeme,"$6"))
	{
		return 6;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$a3")||\
		!strcmp(lexeme.chaine_lexeme,"$7"))
	{
		return 7;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t0")||\
		!strcmp(lexeme.chaine_lexeme,"$8"))
	{
		return 8;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t1")||\
		!strcmp(lexeme.chaine_lexeme,"$9"))
	{
		return 9;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t2")||\
		!strcmp(lexeme.chaine_lexeme,"$10"))
	{
		return 10;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t3")||\
		!strcmp(lexeme.chaine_lexeme,"$11"))
	{
		return 11;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t4")||\
		!strcmp(lexeme.chaine_lexeme,"$12"))
	{
		return 12;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t5")||\
		!strcmp(lexeme.chaine_lexeme,"$13"))
	{
		return 13;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t6")||\
		!strcmp(lexeme.chaine_lexeme,"$14"))
	{
		return 14;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t7")||\
		!strcmp(lexeme.chaine_lexeme,"$15"))
	{
		return 15;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s0")||\
		!strcmp(lexeme.chaine_lexeme,"$16"))
	{
		return 16;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s1")||\
		!strcmp(lexeme.chaine_lexeme,"$17"))
	{
		return 17;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s2")||\
		!strcmp(lexeme.chaine_lexeme,"$18"))
	{
		return 18;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s3")||\
		!strcmp(lexeme.chaine_lexeme,"$19"))
	{
		return 19;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s4")||\
		!strcmp(lexeme.chaine_lexeme,"$20"))
	{
		return 20;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s5")||\
		!strcmp(lexeme.chaine_lexeme,"$21"))
	{
		return 21;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s6")||\
		!strcmp(lexeme.chaine_lexeme,"$22"))
	{
		return 22;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$s7")||\
		!strcmp(lexeme.chaine_lexeme,"$23"))
	{
		return 23;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t8")||\
		!strcmp(lexeme.chaine_lexeme,"$24"))
	{
		return 24;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$t9")||\
		!strcmp(lexeme.chaine_lexeme,"$25"))
	{
		return 25;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$k0")||\
		!strcmp(lexeme.chaine_lexeme,"$26"))
	{
		return 26;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$k1")||\
		!strcmp(lexeme.chaine_lexeme,"$27"))
	{
		return 27;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$gp")||\
		!strcmp(lexeme.chaine_lexeme,"$28"))
	{
		return 28;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$sp")||\
		!strcmp(lexeme.chaine_lexeme,"$29"))
	{
		return 29;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$fp")||\
		!strcmp(lexeme.chaine_lexeme,"$30"))
	{
		return 30;
	}
	if (!strcmp(lexeme.chaine_lexeme,"$ra")||\
		!strcmp(lexeme.chaine_lexeme,"$31"))
	{
		return 31;
	}

	ecriremessage(NIVEAU_ERROR,"Ligne %03d : << %s >> doit etre un registre.\n",\
				  lexeme.num_ligne_lexeme,lexeme.chaine_lexeme);
	exit(EXIT_FAILURE);

}

/*
typedef enum
{
    TYPE_FIN_DE_CHAINE = -1,
    TYPE_WORD = 1,
    TYPE_BYTE = 2,
    TYPE_SPACE= 3,
} TYPE_DE_DIRECTIVE;

typedef struct
{
    TYPE_DE_DIRECTIVE directive;
    LISTE *tab_liste;	//chaine de Liste
} LIGNE_DIRECTIVE_ASM;
*/

/*  Fonction qui fait doublon avec construire_segment_data
void traduire_liste_data(LIGNE_DIRECTIVE_ASM* liste_data)
{
    int i,j;

    for(i=0; liste_data[i].directive!=-1 ; i++)
    {
        if (liste_data[i].directive == TYPE_BYTE || liste_data[i].directive == TYPE_WORD || liste_data[i].directive == TYPE_SPACE )
        {
            liste_data[i].nombre_de_valeurs=compte_variables(liste_data[i].tab_liste);
            liste_data[i].chaine_valeur=calloc( ( liste_data[i].nombre_de_valeurs ), sizeof(long long int) );
            if (!(liste_data[i].chaine_valeur))
            {
                ecriremessage(NIVEAU_ERROR, "Allocation memoire echouee dans analysesyntaxiquebis:traduire_liste_data().\n");    // Au secours !
                exit(EXIT_FAILURE); // sauvons les meubles
            }
            for(j=0; !est_vide(liste_data[i].tab_liste[j]) ; j++)
            {
                liste_data[i].chaine_valeur[j]=lire_nombre(liste_data[i].tab_liste[j]);
                if ( (liste_data[i].directive == TYPE_SPACE) && liste_data[i].chaine_valeur[j]<0 )
                {
                    ecriremessage(NIVEAU_WARNING,"Ligne %03d : La directive .space a pour argument le nombre negatif %d.\n", ( ( (ELEMENT_LEXEME*)( (liste_data[i].tab_liste[0])->element ) )->num_ligne_lexeme ) , liste_data[i].chaine_valeur[j]);
                }
                liberer_liste_lexemes(liste_data[i].tab_liste[j]);
            }
        }
    }
}
*/


int lire_nombre(LISTE ligne_compliquee)    // cette liste correspond à t_direct.tab_liste[i] par exemple
{
    short int signe=0;
    long int nombre = 0;    // long long int is loooooooong
    if (LONG_MAX < (pow(2,31)-1) )
    {
        ecriremessage(NIVEAU_WARNING, "Sur ce systeme, le nombre maximal utilisable, %d, est inferieur a 2^31-1 ce qui empeche de coder correctement grands nombres et nombres negatifs !", LONG_MAX);
    }
    LISTE pointeurliste=ligne_compliquee;
    if(!est_vide(pointeurliste))
    {
		ecriremessage(NIVEAU_DEBUG,"--- Lecture nombre ---\n");
        switch( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->type_de_lexeme)
        {
        default:
            ecriremessage(NIVEAU_ERROR, "Ligne %03d : La ligne de data a simplifier contient le lexeme << %s >> de type invalide (ici) : %d\n", \
                          ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme, \
                          ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme, \
                          ( (ELEMENT_LEXEME*)(pointeurliste->element) )->type_de_lexeme);
            exit(EXIT_FAILURE);

        case TYPE_Plus:
            if (signe !=0)
            {
                ecriremessage(NIVEAU_ERROR, "Ligne %03d : Il y a plus d\'un symbole definissant le signe du nombre.\n", \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme );
                exit(EXIT_FAILURE);
            }
            signe = 1;
            ecriremessage(NIVEAU_DEBUG, "Signe positif\n");
            pointeurliste=pointeurliste->suivant;
            break;

        case TYPE_Minus:
            if (signe !=0)
            {
                ecriremessage(NIVEAU_ERROR, "Ligne %03d : Il y a plus d\'un symbole definissant le signe du nombre.\n", \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme );
                exit(EXIT_FAILURE);
            }
            signe =  -1;
            ecriremessage(NIVEAU_DEBUG, "Signe negatif\n");
            pointeurliste=pointeurliste->suivant;
            break;

        case TYPE_Valeur_decimale:
            if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%ld", &nombre) !=1 )
            {
                ecriremessage(NIVEAU_ERROR, "Ligne %03d : La conversion du nombre decimal %s n\'a pas pu etre effectuee.\n", \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme, \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
                exit(EXIT_FAILURE);
            }
            ecriremessage(NIVEAU_DEBUG, "Valeur decimale %d\n", nombre);
            break;

        case TYPE_Valeur_hexadecimale:
            if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lx", &nombre) !=1 )
            {
                ecriremessage(NIVEAU_ERROR, "Ligne %03d : La conversion du nombre hexadecimal %s n\'a pas pu etre effectuee, valeur lue : %d.\nvaleur de retour de sscanf : %d\n", \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme, \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme, \
                              nombre, \
                              sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lx", &nombre));
                exit(EXIT_FAILURE);
            }
            ecriremessage(NIVEAU_DEBUG, "Valeur hexadecimale %08X = %d\n", nombre, nombre);
            break;

        case TYPE_Valeur_octale:
            if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lo", &nombre) !=1 )
            {
                ecriremessage(NIVEAU_ERROR, "Ligne %03d : La conversion du nombre octal %s n\'a pas pu etre effectuee.\n", \
                              ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme, \
                               ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
                exit(EXIT_FAILURE);
            }
            ecriremessage(NIVEAU_DEBUG, "Valeur octale %08o = %d\n", nombre, nombre);
            break;
        }
		//pointeurliste=pointeurliste->suivant;
    }
    if (signe) nombre*=signe;
    ecriremessage(NIVEAU_DEBUG, "Nombre << %d >> lu dans les lexemes\n", nombre);
    return nombre;
}

int lire_adressage_indirect(LISTE ligne_compliquee, int *val_registre)    // cette liste correspond à t_direct.tab_liste[i] par exemple
{
    short int signe=0;
	int parenthese = 0;
    long int nombre = 0;    // long long int is looooooong
    if (LONG_MAX < (pow(2,31)-1) )
    {
        ecriremessage(NIVEAU_WARNING, "Sur ce systeme, le nombre maximal utilisable, %d, est inferieur a 2^31-1 ce qui empeche de coder correctement grands nombres et nombres negatifs !", LONG_MAX);
    }
    LISTE pointeurliste=ligne_compliquee;
    while(!est_vide(pointeurliste))
    {
		ecriremessage(NIVEAU_DEBUG,"--- Lecture adressage indirect --- Lexeme : %s\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
        switch( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->type_de_lexeme)
        {
			default:
				ecriremessage(NIVEAU_ERROR, "La ligne de data a simplifier contient le type de lexeme invalide (ici) : %s, correspondant au lexeme : <%s>\n", traduire_type_lexeme( (
(ELEMENT_LEXEME*)(pointeurliste->element) )->type_de_lexeme ) , ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
				exit(EXIT_FAILURE);

			case TYPE_Plus:
				if (parenthese) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : Syntaxe incorrecte : il y a une parenthese en trop apres un signe +.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				if (signe !=0)
				{
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : Il y a plus d\'un symbole definissant le signe d\'un nombre.\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme );
					exit(EXIT_FAILURE);
				}
				signe = 1;

				break;

			case TYPE_Minus:
				if (parenthese) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte : il y a une parenthese en trop apres un signe -.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				if (signe !=0)
				{
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : Il y a plus d\'un symbole definissant le signe d\'un nombre.\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme );
					exit(EXIT_FAILURE);
				}
				signe =  -1;

				break;

			case TYPE_Valeur_decimale:
				if (parenthese) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte. Il y a une parenthese apres un nombre decimal.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%ld", &nombre) !=1 )
				{
					ecriremessage(NIVEAU_ERROR, "La conversion du nombre decimal %s n\'a pas pu etre effectuee.\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
					exit(EXIT_FAILURE);
				}
				parenthese =1;
				break;

			case TYPE_Valeur_hexadecimale:
				if (parenthese) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte. Il y a une parenthese apres un nombre hexadecimal.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}

				if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lx", &nombre) !=1 )
				{
					ecriremessage(NIVEAU_ERROR, "La conversion du nombre hexadecimal %s n\'a pas pu etre effectuee, valeur lue : %d.\nvaleur de retour de sscanf : %d\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme, nombre, sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lx", &nombre));
					exit(EXIT_FAILURE);
				}
				ecriremessage(NIVEAU_DEBUG,"\t\t\t\t 0x%x\n",nombre);
				parenthese =1;
				break;

			case TYPE_Valeur_octale:
				if (parenthese) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte. Il y a une parenthese apres un nombre octal.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}

				if ( sscanf( ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme , "%lo", &nombre) !=1 )
				{
					ecriremessage(NIVEAU_ERROR, "La conversion du nombre octal %s n\'a pas pu etre effectuee.\n", ( (ELEMENT_LEXEME*)(pointeurliste->element) )->chaine_lexeme);
					exit(EXIT_FAILURE);
				}
				parenthese =1;
				break;

			case TYPE_Parenthese_gauche :
				if (parenthese != 1) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte : Parenthese gauche au mauvais endroit.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				parenthese =2;
				break;

			case TYPE_Registre :
				if (parenthese != 2) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte. Registre au mauvais endroit.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				parenthese =3;

				*val_registre = num_registre( *( (ELEMENT_LEXEME*)(pointeurliste->element) ) );
				break;

			case TYPE_Parenthese_droite:
				if (parenthese != 3) {
					ecriremessage(NIVEAU_ERROR, "Ligne %03d : syntaxe incorrecte. Parenthese droite au mauvais endroit.\n",\
								  ( (ELEMENT_LEXEME*)(pointeurliste->element) )->num_ligne_lexeme);
					exit(EXIT_FAILURE);
				}
				parenthese =4;
				break;
        }
		pointeurliste=pointeurliste->suivant;
    }


	ecriremessage(NIVEAU_DEBUG,"---Fin lecture adressage indirect : nombre = 0x%x, signe = %d, nombre*signe = %d <=> 0x%X\n"\
				  ,nombre, signe,nombre*signe,nombre*signe);

	if (nombre >=0x8000) return -1;
    if (signe<0) return ((unsigned int)(nombre*signe)) % 0x10000;
    else return nombre;
}

/*
int compte_variables(LISTE* ligne)  // on compte le nombre de variables dans un .byte ou un .word
{
    int j=0;
    while (!est_vide(ligne[j]) )
    {
        /// precaution
        if ( ((ELEMENT_LEXEME*)&ligne[j])->type_de_lexeme>NOMBRE_TYPES || \
             ((ELEMENT_LEXEME*)&ligne[j])->type_de_lexeme<0 )
        {

            ecriremessage(NIVEAU_DEBUG, \
                          "====/!\\==== BRACE FOR IMPACT ====/!\\====\n");
            ecriremessage(NIVEAU_ERROR, \
                          "Erreur detectee : Une liste de data a ete mal initialisee, ce qui va probablement causer une erreur de segmentation.\n");
            ecriremessage(NIVEAU_DEBUG, \
                          "Liste fautive : %p et element fautif d\'indice %d, le type errone detecte : %d n\'appartient pas a [%d-%d]\n", \
                          ligne[j], \
                          j, \
                          ((ELEMENT_LEXEME*)&ligne[j])->type_de_lexeme, \
                          0, \
                          NOMBRE_TYPES);
        }
        j++;
    }
    return j;
}
*/

unsigned int calculer_decalage_segment_data(TYPE_DE_DIRECTIVE type_directive, unsigned int nombre_de_valeurs, int valeur) // Il ne doit rester que .space .byte et .word ici.
{
    // NB  : (a / b) * b + a % b == a
    // NB2 : si on optimise la rapidité d'exécution du code attention à -ffast-math (-FUNsafe-math ?)
    unsigned int decalage=0;
    switch(type_directive)
    {
		default:
			ecriremessage(NIVEAU_ERROR, \
						  "Type de directive %d invalide rencontré lors de calculer_adresse_segment_data().\n", \
						  type_directive);
			exit(EXIT_FAILURE);
			break;

		case TYPE_BYTE:
			decalage=TAILLE_BYTE*nombre_de_valeurs;    // taille_byte est dans gestiondetypes.h
			break;

		case TYPE_WORD:
			decalage=TAILLE_WORD*nombre_de_valeurs;    // taille_word est dans gestiondetypes.h
			break;

		case TYPE_SPACE:
			if (valeur<0)
			{
				ecriremessage(NIVEAU_ERROR, "Le .space a un argument negatif : %d.\n", valeur);
				exit(EXIT_FAILURE);
			}
			decalage=valeur;    // car un .space a un seul argument
			break;

    }
    return decalage;
}

unsigned int aligner(unsigned int adresse_en_cours)
{
	int adresse_alignee = adresse_en_cours;
    if (adresse_en_cours%ALIGNEMENT)    // si on n'est pas aligné
    {
        adresse_alignee+=ALIGNEMENT-adresse_en_cours%ALIGNEMENT;    // on s'aligne
    }
	//ecriremessage(NIVEAU_INFO,"=========Decalage actif=========\n%d -> %d\n",adresse_en_cours,adresse_alignee);
    return adresse_alignee;
}

LIGNE_DIRECTIVE_ASM * construire_segment_data(LIGNE_DIRECTIVE_ASM* tableau_directives,LISTE Letq)
{
    unsigned int adresse_en_cours = 0;
    unsigned int i=0;
    unsigned int j=0;
    ecriremessage(NIVEAU_DEBUG, \
                  "==== DEBUT DE LA CONSTRUCTION DU SEGMENT DATA ====\n");

    for(i=0; tableau_directives[i].directive!=TYPE_FIN_DE_CHAINE; i++)  // tant qu'on n'est pas a la fin du tableau data
    {
        tableau_directives[i].chaine_valeur = NULL; // initialisation pour eviter les surprises plus loin a la liberation

        if (tableau_directives[i].directive==TYPE_BYTE || \
            tableau_directives[i].directive==TYPE_WORD || \
            tableau_directives[i].directive==TYPE_SPACE)
        {
            /// Normalement on connait deja le nombre de valeurs qu'il va falloir allouer
            ecriremessage(NIVEAU_DEBUG, \
                          "Allocation d'un tableau de %d long long int pour stocker les operandes\n", tableau_directives[i].nombre_de_valeurs);

            /// Allouer le tableau de valeurs
            tableau_directives[i].chaine_valeur = calloc(tableau_directives[i].nombre_de_valeurs, sizeof(long long int));
            if ( !(tableau_directives[i].chaine_valeur) )
            {
                ecriremessage(NIVEAU_ERROR, \
                              "Dans analysesyntaxiquebis.c:construire_segment_data(): \
                              l\'allocation du tableau de chaines lors de la creation de la ligne d\'adresse %04X a echoue.", \
                              adresse_en_cours);
                ecriremessage(NIVEAU_ERROR, "Fermeture du programme...");
                exit(EXIT_FAILURE);
            }

            /// Mettre toutes les valeurs dans le tableau (on calcule les adresses memoire plus tard)

            for(j=0; j<tableau_directives[i].nombre_de_valeurs; j++)
            {
                tableau_directives[i].chaine_valeur[j]=lire_nombre(tableau_directives[i].tab_liste[j]);
			}
			if (tableau_directives[i].directive == TYPE_WORD)
				adresse_en_cours = aligner(adresse_en_cours);
			//printf("%d\n",adresse_en_cours);
			reaffecter_etq_data(Letq,i,adresse_en_cours);
			tableau_directives[i].adresse_ligne=adresse_en_cours;
			adresse_en_cours+=calculer_decalage_segment_data(tableau_directives[i].directive, tableau_directives[i].nombre_de_valeurs, tableau_directives[i].chaine_valeur[0]);



            // allouer le tableau de "nombre_de_valeurs" entiers, elle sera a liberer plus tard
            // mettre chaque valeur dans le tableau et calculer l'adresse ligne
            // sur du .space n on met n octets puis on se realigne sur un multiple de 4
            // sur du .word on met 4 octets
            // sur du .byte on prend autant d'octets que de valeurs puis on se realigne sur un multiple de 4

            //

        }
        /// Précautions
        else ecriremessage(NIVEAU_DEBUG, "!!! Directive de type negatif ou nul = << %d >> rencontree, ce n\'est pas normal...\n", tableau_directives[i].directive);

    }

    ecriremessage(NIVEAU_DEBUG, "==== FIN DE LA CONSTRUCTION DU SEGMENT DATA ====\n");
    return tableau_directives;
}

void reaffecter_etq_data(LISTE Letq, unsigned int indice_data, unsigned int adresse_data)
{
	LISTE index;
	for (index = Letq; !est_vide(index); index=index->suivant) {
		if (  ((ELEMENT_ETIQUETTE *)(index->element))-> type ==-1  &&  ((ELEMENT_ETIQUETTE *)(index->element))-> num_ligne == indice_data )
		{
			((ELEMENT_ETIQUETTE *)(index->element))-> num_ligne = adresse_data/4;
			((ELEMENT_ETIQUETTE *)(index->element))-> type =-2;
		}
	}
}

